package com.rm.zeyou.util.threadpool;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

@Component
public class ThreadPoolUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtil.class);
    private static ThreadPoolExecutor threadPool = null;
    private static final String POOL_NAME = "myPool";

    // 将硬编码的参数改为可配置
    private static int blockingQueueLength = 1000;

    private static int keepAliveTime = 60000;

    //private ThreadPoolUtil() {
    //    throw new IllegalStateException("utility class");
    //}

    /**
     * 提供一个方法安全关闭线程池
     */
    public static void shutdown() {
        if (threadPool != null) {
            threadPool.shutdown();
            threadPool = null;
            LOGGER.info("线程池已安全关闭");
        }
    }

    /**
     * 无返回值直接执行
     *
     * @param runnable 需要运行的任务
     */
    public static void execute(Runnable runnable) {
        getThreadPool().execute(runnable);
    }

    /**
     * 有返回值执行
     *
     * @param callable 需要运行的任务
     */
    public static <T> Future<T> submit(Callable<T> callable) {
        return getThreadPool().submit(callable);
    }

    private static synchronized ThreadPoolExecutor getThreadPool() {
        if (threadPool == null) {
            int cpuNum = Runtime.getRuntime().availableProcessors();
            int maximumPoolSize = cpuNum * 2 + 1;

            // 使用CallerRunsPolicy策略
            threadPool = new ThreadPoolExecutor(maximumPoolSize - 1, maximumPoolSize,
                    keepAliveTime, TimeUnit.MILLISECONDS,
                    new LinkedBlockingDeque<>(blockingQueueLength),
                    new ThreadFactoryBuilder().setNameFormat(POOL_NAME + "-%d").build(),
                    new ThreadPoolExecutor.CallerRunsPolicy() {
                        @Override
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                            LOGGER.warn("线程爆炸了，当前运行线程总数：{}，活动线程数：{}。等待队列已满，等待运行任务数：{}，被拒绝任务：{}",
                                    e.getPoolSize(),
                                    e.getActiveCount(),
                                    e.getQueue().size(),
                                    r.toString());
                        }
                    });
        }

        return threadPool;
    }
}
